package com.cloud.config;

import com.alibaba.druid.pool.DruidDataSource;

import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;

import java.sql.SQLException;
import java.util.Properties;

import javax.annotation.PreDestroy;

@Configuration
//mybaits dao 搜索路径
@MapperScan("com.cloud.dao")
public class MybatisDataSource {
    @Value("${cn.cloud.server.datasource.driver}")
    protected String driverClass;
    @Value("${cn.cloud.server.datasource.url}")
    protected String jdbcUrl;
    @Value("${cn.cloud.server.datasource.user}")
    protected String dbUser;
    @Value("${cn.cloud.server.datasource.password}")
    protected String dbPwd;
    @Value("${cn.cloud.server.datasource.pool.minIdle}")
    protected Integer minIdle;
    @Value("${cn.cloud.server.datasource.pool.maxActive}")
    protected Integer maxPoolSize;
    @Value("${cn.cloud.server.datasource.pool.initialSize}")
    protected Integer initialSize;
    @Value("${cn.cloud.server.datasource.pool.testOnIdle}")
    protected boolean testOnIdle = true;
    @Value("${cn.cloud.server.datasource.pool.testOnReturn}")
    protected boolean testOnReturn = false;
    @Value("${cn.cloud.server.datasource.pool.testOnBorrow}")
    protected boolean testOnBorrow = false;
    @Value("${cn.cloud.server.datasource.pool.validationQuery}")
    protected String validationQuery;
    @Value("${cn.cloud.server.datasource.timeBetweenEvictionRunsMillis}")
    protected Long timeBetweenEvictionRunsMillis;
    @Value("${cn.cloud.server.datasource.pool.minEvictableIdleTimeMillis}")
    protected Long minEvictableIdleTimeMillis;
    @Value("${cn.cloud.server.datasource.filters}")
    protected String filters;
    @Value("${cn.cloud.server.datasource.pool.connectionProperties}")
    protected Properties connectionProperties;
    @Value("${cn.cloud.server.datasource.pool.poolPreparedStatements}")
    protected Boolean poolPreparedStatements;
    @Value("${cn.cloud.server.datasource.pool.maxPoolPreparedStatementPerConnectionSize}")
    protected Integer maxPoolPreparedStatementPerConnectionSize;
    //mybaits mapper xml搜索路径
    @Value("${cn.cloud.server.datasource.mapperLocations}")
    protected String mapperLocations;

    private DruidDataSource pool;

    @Bean(destroyMethod = "close")
    public DruidDataSource dataSource() throws SQLException {
        this.pool = new DruidDataSource();
        this.pool.setDriverClassName(driverClass);
        this.pool.setUrl(jdbcUrl);
        if (dbUser != null) {
            this.pool.setUsername(dbUser);
        }
        if (dbPwd != null) {
            this.pool.setPassword(dbPwd);
        }
        this.pool.setInitialSize(initialSize);
        this.pool.setMaxActive(maxPoolSize);
        this.pool.setMinIdle(minIdle);
        this.pool.setTestWhileIdle(testOnIdle);
        this.pool.setTestOnReturn(testOnReturn);
        this.pool.setTestOnBorrow(testOnBorrow);
        this.pool.setValidationQuery(validationQuery);
        this.pool.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
        this.pool.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
        this.pool.setFilters(filters);
        this.pool.setConnectProperties(connectionProperties);
        this.pool.setPoolPreparedStatements(poolPreparedStatements);
        this.pool.setMaxPoolPreparedStatementPerConnectionSize(maxPoolPreparedStatementPerConnectionSize);
        this.pool.setMaxWait(60000);
        return this.pool;
    }

    @PreDestroy
    public void close() {
        if (this.pool != null) {
            this.pool.close();
        }
    }

    @Bean
    public SqlSessionFactory sqlSessionFactoryBean() throws Exception {
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(dataSource());
        PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        sqlSessionFactoryBean.setMapperLocations(resolver.getResources(mapperLocations));
        return sqlSessionFactoryBean.getObject();
    }

    @Bean
    public PlatformTransactionManager transactionManager() throws SQLException {
        return new DataSourceTransactionManager(dataSource());
    }
}
